package com.tmsps.common.exception;

import com.tmsps.common.config.prop.ExceptionCode;
import com.tmsps.common.util.result.ResponseBean;
import com.tmsps.common.util.result.ResponseCodeEnum;
import com.tmsps.ne4spring.utils.ChkUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * 全局异常处理
 * @author jiangtao
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionAdvice {

    private ExceptionCode exceptionCode;

    public GlobalExceptionAdvice(ExceptionCode exceptionCode){
        this.exceptionCode = exceptionCode;
    }

    /**
     * 全局异常处理
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseBean handleException(Exception e) {
        log.error("全局捕获异常", e);

        return new ResponseBean(ResponseCodeEnum.EX_SYSTEM);
    }

    /**
     * 处理自定义第三方服务调用异常
     * @param e 自定义异常
     * @return 自定义返回类型
     */
    @ExceptionHandler(MicroServiceException.class)
    @ResponseBody
    public ResponseBean handleMicroServiceException(MicroServiceException e){
        String code = e.getCode();
        String msg = e.getMsg();

        // 第三方服务报错
        String serviceError = "serviceErr-";

        return new ResponseBean(serviceError + code, msg, null);
    }

    /**
     * 处理自定义异常
     * @param e 自定义异常
     * @return 自定义返回类型
     */
    @ExceptionHandler(AppException.class)
    @ResponseBody
    public ResponseBean handleAppException(AppException e){
        ResponseCodeEnum repEnum = e.getRepEnum();
        String appResponseCode = e.getAppResponseCode();

        if(ChkUtil.isNotNull(repEnum)){
            return new ResponseBean(repEnum);
        }
        if(ChkUtil.isNotNull(appResponseCode)){
            return new ResponseBean(appResponseCode,exceptionCode.getMessage(appResponseCode));
        }

        return new ResponseBean(ResponseCodeEnum.EX_SYSTEM);
    }

    /**
     * beanValidation 校验异常处理
     * @param e 具体的错误
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public ResponseBean handleBeanValidation(MethodArgumentNotValidException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = this.formatAllErrorMessages(errors);

        log.info("参数验证不通过：{}", message);

        return new ResponseBean(ResponseCodeEnum.EX_USER_REG_PARAMS.getCode(), message);
    }

    /**
     * beanValidation 校验异常处理
     * @param e 具体的错误
     */
    @ExceptionHandler({BindException.class})
    @ResponseBody
    public ResponseBean handleBeanValidation(BindException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = this.formatAllErrorMessages(errors);

        log.info("参数验证不通过：{}", message);

        return new ResponseBean(ResponseCodeEnum.EX_USER_REG_PARAMS.getCode(), message);
    }

    private String formatAllErrorMessages(List<ObjectError> errors) {
        return errors.get(0).getDefaultMessage();
    }

}

